<template>
  <div class="webgl-letter">
    <h1>WEBGL字母绘制</h1>
    <p>使用WebGL绘制由线段组成的WEBGL字母，展示如何使用基本图形元素组合成复杂的文字图形。</p>

    <el-card class="demo-section">
      <template #header>
        <div class="card-header">
          <h3>WEBGL字母展示</h3>
        </div>
      </template>
      <div class="demo-content">
        <canvas ref="demoCanvas" width="600" height="300"></canvas>
        <div class="control-panel">
          <el-form :model="letterForm" label-width="100px">
            <el-form-item label="线条颜色">
              <el-color-picker v-model="letterForm.lineColor" @change="updateLetters" />
            </el-form-item>
            <el-form-item label="线条宽度">
              <el-slider
                v-model="letterForm.lineWidth"
                :min="1"
                :max="10"
                @change="updateLetters"
              />
            </el-form-item>
          </el-form>
        </div>
      </div>
    </el-card>

    <el-card class="code-section">
      <template #header>
        <div class="card-header">
          <h3>示例代码</h3>
        </div>
      </template>
      <div class="code-content">
        <pre><code>
// 顶点着色器
attribute vec4 a_Position;
void main() {
  gl_Position = a_Position;
}

// 片元着色器
precision mediump float;
uniform vec4 u_Color;
void main() {
  gl_FragColor = u_Color;
}

// JavaScript代码
// 定义字母顶点数据
const letterVertices = {
  'W': [...],
  'E': [...],
  'B': [...],
  'G': [...],
  'L': [...]
};

// 设置线条属性
gl.lineWidth(lineWidth);
gl.uniform4fv(u_Color, [r, g, b, 1.0]);

// 绘制字母
gl.drawArrays(gl.LINE_STRIP, 0, vertexCount);
        </code></pre>
      </div>
    </el-card>

    <el-card class="info-section">
      <template #header>
        <div class="card-header">
          <h3>实现说明</h3>
        </div>
      </template>
      <el-descriptions :column="1" border>
        <el-descriptions-item label="绘制方式">
          使用LINE_STRIP模式连续绘制线段形成字母轮廓
        </el-descriptions-item>
        <el-descriptions-item label="顶点数据">
          每个字母由一系列顶点坐标定义，通过连接这些顶点形成字母形状
        </el-descriptions-item>
        <el-descriptions-item label="样式控制">
          支持自定义线条颜色和宽度，实时更新显示效果
        </el-descriptions-item>
      </el-descriptions>
    </el-card>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { WebGLUtils, colorUtils } from '@/utils/webgl'

const demoCanvas = ref<HTMLCanvasElement | null>(null)
const gl = ref<WebGLRenderingContext | null>(null)
const shaderProgram = ref<WebGLProgram | null>(null)
const webglUtils = ref<WebGLUtils | null>(null)

const letterForm = reactive({
  lineColor: '#409EFF',
  lineWidth: 2
})

// 定义字母顶点数据
const letterVertices = {
  'W': [
    -0.8, 0.3,   // 左上
    -0.7, -0.3,   // 左下
    -0.6, 0.1,    // 中上
    -0.5, -0.3,   // 中下
    -0.4, 0.3     // 右上
  ],
  'E': [
    // 竖线
    -0.3, 0.3,    // 左上
    -0.3, -0.3,   // 左下
    // 上横线
    -0.3, 0.3,    // 左上
    -0.1, 0.3,    // 右上
    // 中横线
    -0.3, 0.0,    // 左中
    -0.1, 0.0,    // 右中
    // 下横线
    -0.3, -0.3,   // 左下
    -0.1, -0.3    // 右下
  ],
  'B': [
    0.0, 0.3,    // 左上
    0.0, -0.3,    // 左下
    0.0, 0.3,     // 回到左上
    0.2, 0.3,     // 上横
    0.3, 0.2,     // 上弧
    0.2, 0.0,     // 中点
    0.0, 0.0,     // 回到中间
    0.2, 0.0,     // 中横
    0.3, -0.1,    // 下弧
    0.2, -0.3,    // 下横
    0.0, -0.3     // 回到左下
  ],
  'G': [
    0.5, 0.2,    // 上弧起点
    0.4, 0.3,     // 上弧
    0.3, 0.3,     // 左上
    0.3, -0.3,    // 左下
    0.4, -0.3,    // 下横
    0.5, -0.2,    // 下弧
    0.5, 0.0,     // 中点
    0.4, 0.0      // 中横
  ],
  'L': [
    0.6, 0.3,    // 左上
    0.6, -0.3,    // 左下
    0.8, -0.3     // 下横
  ]
}

// 初始化WebGL
const initWebGL = () => {
  if (!demoCanvas.value) return

  // 获取WebGL上下文
  gl.value = demoCanvas.value.getContext('webgl')
  if (!gl.value) {
    console.error('Failed to get WebGL context')
    return
  }

  // 创建WebGL工具实例
  webglUtils.value = new WebGLUtils(gl.value)

  // 顶点着色器源码
  const vertexShaderSource = `
    attribute vec4 a_Position;
    void main() {
      gl_Position = a_Position;
    }
  `

  // 片元着色器源码
  const fragmentShaderSource = `
    precision mediump float;
    uniform vec4 u_Color;
    void main() {
      gl_FragColor = u_Color;
    }
  `

  // 创建着色器
  const vertexShader = webglUtils.value.createShader(gl.value.VERTEX_SHADER, vertexShaderSource)
  const fragmentShader = webglUtils.value.createShader(gl.value.FRAGMENT_SHADER, fragmentShaderSource)
  if (!vertexShader || !fragmentShader) return

  // 创建程序并链接着色器
  shaderProgram.value = webglUtils.value.createProgram(vertexShader, fragmentShader)
  if (!shaderProgram.value) return

  gl.value.useProgram(shaderProgram.value)

  // 更新字母
  updateLetters()
}

// 更新字母属性并重绘
const updateLetters = () => {
  if (!gl.value || !shaderProgram.value || !webglUtils.value) return

  // 设置清除颜色并清除
  gl.value.clearColor(0.0, 0.0, 0.0, 1.0)
  gl.value.clear(gl.value.COLOR_BUFFER_BIT)

  // 设置线宽
  gl.value.lineWidth(letterForm.lineWidth)

  // 转换颜色
  const color = colorUtils.hexToRgb(letterForm.lineColor)

  // 获取uniform位置
  const u_Color = gl.value.getUniformLocation(shaderProgram.value, 'u_Color')
  gl.value.uniform4f(u_Color, color.r, color.g, color.b, 1.0)

  // 绘制每个字母
  Object.values(letterVertices).forEach(vertices => {
    // 创建并绑定缓冲区
    const vertexBuffer = webglUtils.value?.createBuffer(new Float32Array(vertices))
    if (!vertexBuffer || !gl.value || !shaderProgram.value) return

    // 设置顶点位置属性
    const a_Position = gl.value.getAttribLocation(shaderProgram.value, 'a_Position')
    gl.value.vertexAttribPointer(a_Position, 2, gl.value.FLOAT, false, 0, 0)
    gl.value.enableVertexAttribArray(a_Position)

    // 根据字母类型选择绘制模式
    if (vertices === letterVertices['E']) {
      // E字母使用LINES模式绘制
      for (let i = 0; i < vertices.length / 4; i++) {
        gl.value.drawArrays(gl.value.LINES, i * 2, 2)
      }
    } else {
      // 其他字母继续使用LINE_STRIP模式
      gl.value.drawArrays(gl.value.LINE_STRIP, 0, vertices.length / 2)
    }
  })
}

// 组件挂载时初始化WebGL
onMounted(() => {
  initWebGL()
})
</script>

<style lang="scss" scoped>
.webgl-letter {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;

  h1 {
    color: #303133;
    margin-bottom: 20px;
  }

  p {
    margin-bottom: 30px;
  }

  .demo-section,
  .code-section,
  .info-section {
    margin: 30px 0;

    .card-header {
      display: flex;
      align-items: center;

      h3 {
        margin: 0;
        color: #409EFF;
      }
    }
  }

  .demo-section {
    .demo-content {
      display: flex;
      gap: 20px;

      canvas {
        border: 1px solid #dcdfe6;
        background-color: #000;
      }

      .control-panel {
        flex: 1;
        padding: 20px;
        background-color: #f8f9fa;
        border-radius: 4px;
      }
    }
  }

  .code-section,
  .info-section {
    .code-content {
      background-color: #f8f9fa;
      padding: 15px;
      border-radius: 4px;

      code {
        font-family: monospace;
        color: #409EFF;
      }

      pre {
        margin: 0;
        white-space: pre-wrap;
      }
    }
  }
}
</style>